home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #4 / Amiga Plus CD - 2000 - No. 4.iso / PowerPC / Dev / PPCRelease / Examples / R.Mainz / msg9 / Msg9.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-03  |  17.5 KB  |  511 lines

  1.  
  2. /*
  3. **
  4. **  $VER: msg9.c 46.1 (3.6.98)
  5. **  Msg9 46.1
  6. **
  7. **  m68k side of Msg9
  8. **
  9. **  Written 1997/1998 by Roland Mainz (gisburn@w-specht.rhein-ruhr.de)
  10. **
  11. */
  12.  
  13. /* Msg9
  14.  *
  15.  * This test program reads from a file (or fills a buffer with random data)
  16.  * and send the messages to the ppc side and shows how long this takes.
  17.  * The Messages are send asyncronous and are re-used after they were replied
  18.  * by the ppc side. Only a fixed number of message is used to do the transfer.
  19.  * Each Message has a Body with a fixed size (except the last
  20.  * message) and the PPC side checks if the msg is received correctly.
  21.  * The whole msg body is also checked each send if it`s
  22.  * 100% correct
  23.  */
  24.  
  25. /* amiga includes */
  26. #include <exec/types.h>
  27. #include <exec/nodes.h>
  28. #include <exec/lists.h>
  29. #include <exec/memory.h>
  30. #include <utility/tagitem.h>
  31. #include <dos/dostags.h>
  32. #include <PowerUP/ppclib/interface.h>
  33. #include <PowerUP/ppclib/memory.h>
  34. #include <PowerUP/ppclib/message.h>
  35. #include <PowerUP/ppclib/tasks.h>
  36.  
  37. /* amiga prototypes */
  38. #include <clib/exec_protos.h>
  39. #include <clib/dos_protos.h>
  40. #include <clib/timer_protos.h>
  41. #include <PowerUP/clib/ppc_protos.h>
  42.  
  43. /* amiga pragmas */
  44. #include <pragmas/exec_pragmas.h>
  45. #include <pragmas/dos_pragmas.h>
  46. #include <pragmas/timer_pragmas.h>
  47. #include <PowerUP/pragmas/ppc_pragmas.h>
  48.  
  49. /* ANSI C includes */
  50. #include <stdio.h>
  51. #include <string.h>
  52.  
  53. /* ppc example support functions */
  54. #include "time.h"
  55. #include "time_protos.h"
  56.  
  57. /* project includes */
  58. #include "msg9.h"
  59.  
  60. /******************************************************************************/
  61.  
  62. /* for V45 includes compatibility */
  63. #ifndef MEMF_NOCACHEM68K
  64. #define MEMF_NOCACHEM68K MEMF_NOCACHESYNCM68K
  65. #endif /* !MEMF_NOCACHEM68K */
  66.  
  67. /******************************************************************************/
  68. /* test code configuration */
  69.  
  70. #define USE_FILE    (1)    /* 1= read from file / 0 = fill msg buffer with test pattern */
  71. #define MSGBODYSIZE (1024) /* size of messages */
  72. #define NUM_MSGS    (8)    /* number of transfer messages */
  73.  
  74. /******************************************************************************/
  75.  
  76. extern struct Library *SysBase,
  77.                       *DOSBase;
  78.  
  79. /******************************************************************************/
  80.  
  81. /* local prototypes */
  82. static LONG SeekRead( struct FileHandle *, LONG, LONG, APTR, ULONG );
  83.  
  84. /******************************************************************************/
  85.  
  86. /* main program entry */
  87. int main( void )
  88. {
  89.     struct Library *PPCLibBase;
  90.     ULONG           i,
  91.                     j;
  92.  
  93.     Printf( "Opening ppc.library >= V44\n" );
  94.  
  95.     /* Note: The PPC side uses ppc.library V46-only functions
  96.      *       this side can run under V44
  97.      */
  98.     if( PPCLibBase = OpenLibrary( "ppc.library", 46UL ) )
  99.     {
  100. #if USE_FILE
  101.       LONG  filesize = 0UL;        /* file size (sum of all send blocks) */
  102. #else
  103.       LONG  filesize = 512 * 1024; /* size of bytes to send */
  104. #endif /* USE_FILE */
  105.  
  106.  
  107. #if USE_FILE
  108.       STRPTR filename = "C:Ed"; /* A big file, should be >= 5 MB...
  109.                                  * "C:Ed" is only used here because IMHO every (99.9899%)
  110.                                  * Amiga has this file...
  111.                                  */
  112.       BPTR   fh;
  113.  
  114.       Printf( "Opening test file \"%s\"\n", filename );
  115.  
  116.       if( fh = Open( filename, MODE_OLDFILE ) )
  117.       {
  118. #endif /* USE_FILE */
  119.         APTR MyTimerObject;
  120.  
  121.         Printf( "Create timer object\n" );
  122.  
  123.         if( MyTimerObject = TimerCreateObject() )
  124.         {
  125.           APTR ElfObject;
  126.  
  127.           Printf( "Loading PPC object\n" );
  128.  
  129.           if( ElfObject = PPCLoadObject( "PROGDIR:Msg9PPC.elf" ) )
  130.           {
  131.             APTR ReplyPort;
  132.  
  133.             Printf( "Creating reply port\n" );
  134.  
  135.             if( ReplyPort = PPCCreatePort( NULL ) )
  136.             {
  137.               APTR StartupMsg;
  138.  
  139.               if( StartupMsg = PPCCreateMessage( ReplyPort, (ULONG)sizeof( struct StartupData ) ) )
  140.               {
  141.                 struct StartupData *StartupData;
  142.  
  143.                 Printf( "Allocating StartupData\n" );
  144.  
  145.                 if( StartupData = (struct StartupData *)PPCAllocVec( (ULONG)sizeof( struct StartupData ), MEMF_PUBLIC ) )
  146.                 {
  147.                   APTR Task;
  148.  
  149.                   StartupData -> BodySize = MSGBODYSIZE;
  150.  
  151.                   Printf( "Creating PPC task\n" );
  152.  
  153.                   if( Task = PPCCreateTaskTags( ElfObject, PPCTASKTAG_STARTUP_MSG,       (ULONG) StartupMsg,
  154.                                                            PPCTASKTAG_STARTUP_MSGDATA,   (ULONG) StartupData,
  155.                                                            PPCTASKTAG_STARTUP_MSGLENGTH, sizeof( StartupData ),
  156.                                                            PPCTASKTAG_STARTUP_MSGID,     0UL,
  157.                                                            PPCTASKTAG_MSGPORT,           TRUE,
  158. #if USE_PPC_STDIO
  159.                                                            PPCTASKTAG_INPUTHANDLE,       (ULONG) Input(),
  160.                                                            PPCTASKTAG_OUTPUTHANDLE,      (ULONG) Output(),
  161.                                                            NP_CloseInput,                FALSE,
  162.                                                            NP_CloseOutput,               FALSE,
  163. #endif /* USE_PPC_STDIO */
  164.                                                            TAG_DONE ) )
  165.                   {
  166.                     APTR PPCPort;
  167.  
  168.                     if( PPCPort = (APTR)PPCGetTaskAttrsTags( Task, PPCTASKINFOTAG_MSGPORT, NULL, TAG_DONE ) )
  169.                     {
  170.                       signed int  m;
  171.                       APTR        msg[ NUM_MSGS ]    = { 0 };
  172.                       UBYTE      *buffer[ NUM_MSGS ] = { 0 };
  173.                       BOOL        success            = TRUE;
  174.                       int         outstanding        = 1; /* the startup message is pending... */
  175.  
  176.                       Printf( "Allocating memory for message body\n" );
  177.  
  178.                       for( m = 0 ; m < NUM_MSGS ; m++ )
  179.                       {
  180.                         /* Allocate a message */
  181.                         msg[ m ]    =          PPCCreateMessage( ReplyPort, MSGBODYSIZE );
  182.  
  183.                         /* Allocate a message buffer. The additional 32 bytes are only for internal testing
  184.                          * NOTE: Some previous versions (e.g. V45.20) of ppc.library had a bug in the cache
  185.                          *       code which caused that the ppc side sometimes got trashed messages.
  186.                          *       Use MEMF_NOCACHEM68KSYNC in this case. (MEMF_NOCACHEM68K is only
  187.                          *       available in V46 or higher).
  188.                          *       This bug has been fixed in ppc.library V46.
  189.                          */
  190.                         buffer[ m ] = (UBYTE *)PPCAllocVec( (MSGBODYSIZE + 32), (MEMF_PUBLIC /*| MEMF_NOCACHEM68K*/) );
  191.  
  192.                         if( (!msg[ m ]) || (!buffer[ m ]) )
  193.                         {
  194.                           success = FALSE;
  195.                         }
  196.                       }
  197.  
  198.                       if( success )
  199.                       {
  200.                         APTR   freemsg       = NULL;
  201.                         UBYTE *freemsgbuffer = NULL;
  202.                         BOOL   done          = FALSE;
  203.  
  204.                         m = 0; /* First unsend message... */
  205.  
  206.                         Printf( "Sending file buffers ASYNC, check the msg validation and wait for them...\n" );
  207.  
  208.                         { /* Begin of stopwatch block...*/
  209.                           TimerSetAttr( MyTimerObject, TIMERTAG_START );
  210.  
  211.                           while( !done )
  212.                           {
  213.                             /* No message free ? Then try to fetch one from our "free"-pool or wait for a replied one... */
  214.                             if( freemsg == NULL )
  215.                             {
  216.                               /* Is there a message which did not see the ppc yet ? */
  217.                               if( m < NUM_MSGS )
  218.                               {
  219.                                 freemsg       = msg[ m ];
  220.                                 freemsgbuffer = buffer[ m ];
  221.                                 m++;
  222.                               }
  223.                               else
  224.                               {
  225.                                 /* Wait for a message to be re-used... */
  226.                                 PPCWaitPort( ReplyPort );
  227.  
  228.                                 if( freemsg = PPCGetMessage( ReplyPort ) )
  229.                                 {
  230.                                   freemsgbuffer = (UBYTE *)PPCGetMessageAttr( freemsg, PPCMSGTAG_DATA );
  231.                                   outstanding--;
  232.                                 }
  233.                               }
  234.                             }
  235.  
  236.                             /* Any free message to send ? */
  237.                             if( freemsg )
  238.                             {
  239.                               LONG requestsize = MSGBODYSIZE,
  240.                                    readsize;
  241.  
  242.                               /* Fill the buffer */
  243. #if USE_FILE
  244. #if 0
  245.                               readsize = Read( fh, freemsgbuffer, requestsize );
  246. #else
  247.                               readsize = SeekRead( (struct FileHandle *)BADDR( fh ), 0L, OFFSET_CURRENT, freemsgbuffer, requestsize );
  248. #endif
  249. #else
  250.                               /* Fill buffer with "random" data */
  251.                               {
  252.                                 ULONG f;
  253.  
  254.                                 if( (filesize - requestsize) <= 0L )
  255.                                 {
  256.                                   readsize = filesize;
  257.                                 }
  258.                                 else
  259.                                 {
  260.                                   readsize = requestsize;
  261.                                 }
  262.  
  263.                                 for( f = 0 ; f < readsize ; f++ )
  264.                                 {
  265.                                   freemsgbuffer[ f ] = ((f - 1024) & 0xFF); /* Not a good rand replacement :-( */
  266.                                 }
  267.  
  268.                                 filesize -= readsize;
  269.                               }
  270. #endif /* USE_FILE */
  271.  
  272.                               /* EOF / error */
  273.                               if( readsize != requestsize )
  274.                               {
  275.                                 done = TRUE;
  276.                               }
  277.  
  278.                               /* In the error case we don't know what happed with the buffer, therefore... */
  279.                               if( readsize == -1L )
  280.                               {
  281.                                 readsize = 0L;
  282.                               }
  283.  
  284. #if USE_FILE
  285.                               filesize += readsize;
  286. #endif /* USE_FILE */
  287.  
  288.                               /* Calc checksum (checksum -> i)...  */
  289.                               for( i = 0UL, j = 0UL ; j < readsize ; j++ )
  290.                               {
  291.                                 i += freemsgbuffer[ j ];
  292.                               }
  293.  
  294.                               if( PPCSendMessage( PPCPort, freemsg, freemsgbuffer, readsize, i ) )
  295.                               {
  296.                                 freemsg       = NULL;
  297.                                 freemsgbuffer = NULL;
  298.                                 outstanding++;
  299.                               }
  300.                               else
  301.                               {
  302.                                 Printf( "can't send ppc message %ld\n", (LONG)i );
  303.                               }
  304.                             }
  305.                           }
  306.  
  307.                           TimerSetAttr( MyTimerObject, TIMERTAG_STOP );
  308.                           TimerShow( MyTimerObject );
  309.                         } /* End of stopwatch block...*/
  310.  
  311.                         Printf( "Waiting for Task Finish Msg (Outstanding messages: %ld)...\n", (LONG)outstanding );
  312.  
  313.                         while( outstanding > 0 )
  314.                         {
  315.                           APTR msg;
  316.  
  317.                           if( msg = PPCGetMessage( ReplyPort ) )
  318.                           {
  319.                             outstanding--;
  320.  
  321.                             if( msg == StartupMsg )
  322.                             {
  323.                               Printf( "Ahh..the expected Startup=Finish Msg was received.\n"
  324.                                       "Now we can savely free all resources when all msgs are back.\n" );
  325.                             }
  326.                             else
  327.                             {
  328. #if 0
  329.                               Printf( "Some non replied Msg 0x%lx was found..wait\n", msg );
  330. #endif
  331.                               PPCWaitPort( ReplyPort );
  332.                             }
  333.                           }
  334.                           else
  335.                           {
  336.                             Printf( "PPCGetMessage retuned NULL\n" );
  337.                           }
  338.                         }
  339.  
  340. #if USE_FILE
  341.                         Printf( "the file has %lu bytes\n", filesize );
  342. #endif /* USE_FILE */
  343.                       }
  344.                       else
  345.                       {
  346.                         Printf( "Couldn't allocate a message or a buffer\n" );
  347.                       }
  348.  
  349.                       /* Get rid of the messages and their buffers */
  350.                       for( m = NUM_MSGS - 1 ; m >= 0 ; m-- )
  351.                       {
  352.                         PPCFreeVec( buffer[ m ] );
  353.                         PPCDeleteMessage( msg[ m ] );
  354.                       }
  355.                     }
  356.                     else
  357.                     {
  358.                       Printf( "Could not find the PPCTask's msgport\n" );
  359.                     }
  360.                   }
  361.                   else
  362.                   {
  363.                     Printf( "Could not create PPC task\n" );
  364.                   }
  365.  
  366.                   PPCFreeVec( StartupData );
  367.                 }
  368.                 else
  369.                 {
  370.                   Printf( "Could not alloc Startup Data\n" );
  371.                 }
  372.  
  373.                 PPCDeleteMessage( StartupMsg );
  374.               }
  375.               else
  376.               {
  377.                 Printf( "Could not create Startup message\n" );
  378.               }
  379.  
  380.               PPCDeletePort( ReplyPort );
  381.             }
  382.             else
  383.             {
  384.               Printf( "Could not create reply port\n" );
  385.             }
  386.  
  387.             Printf( "Unloading PPC object\n" );
  388.             PPCUnLoadObject( ElfObject );
  389.           }
  390.           else
  391.           {
  392.             Printf( "Could not load the elf object\n" );
  393.           }
  394.  
  395.           Printf( "Disposing timer object\n" );
  396.  
  397.           TimerDeleteObject( MyTimerObject );
  398.         }
  399.         else
  400.         {
  401.           Printf( "Can't create timer object\n" );
  402.         }
  403.  
  404. #if USE_FILE
  405.         (void)Close( fh );
  406.       }
  407.       else
  408.       {
  409.         Printf( "Can't open '%s' %ld\n", filename, IoErr() );
  410.       }
  411. #endif /* USE_FILE */
  412.  
  413.       Printf( "Closing ppc.library\n" );
  414.       CloseLibrary( PPCLibBase );
  415.     }
  416.     else
  417.     {
  418.       Printf( "Could not open ppc.library v46\n" );
  419.     }
  420.  
  421.     return( RETURN_OK );
  422. }
  423.  
  424.  
  425. /* from mpegvideo.datatype V2.5 */
  426. /* This function executes a seek and read. Both DosPackets are send async that the handler process
  427.  * can execute them as fast as possible.
  428.  * The code avoids any memory allocation or accesses to AbsExecbase (like dos.library does).
  429.  * Note: In the case of failure the current file position can only be obtained using a
  430.  * Seek( fh, 0L, OFFSET_CURRENT ).
  431.  */
  432. static
  433. LONG SeekRead( struct FileHandle *fh, LONG seek_pos, LONG seek_mode, APTR read_buffer, ULONG read_len )
  434. {
  435.     LONG                   reslen   = -1L;
  436.     LONG                   error    = 0L;
  437.     struct MsgPort        *mp       = (&(((struct Process *)FindTask( NULL )) -> pr_MsgPort));
  438.     struct StandardPacket  seek_sp,
  439.                            read_sp;
  440.     struct DosPacket      *seek_dp  = (&(seek_sp . sp_Pkt));
  441.     struct DosPacket      *read_dp  = (&(read_sp . sp_Pkt));
  442.     LONG                   numpkt   = 0L; /* pending packets */
  443.  
  444.     /* Send seek (if neccesary) */
  445.     if( !((seek_mode == OFFSET_CURRENT) && (seek_pos == 0L)) )
  446.     {
  447.       seek_sp . sp_Msg . mn_Node . ln_Type = NT_MESSAGE;
  448.       seek_sp . sp_Msg . mn_Node . ln_Name = (STRPTR)seek_dp;
  449.       seek_sp . sp_Msg . mn_Length         = sizeof( struct DosPacket );
  450.       seek_sp . sp_Pkt . dp_Link           = (&(seek_sp . sp_Msg));
  451.  
  452.       seek_dp -> dp_Type = ACTION_SEEK;
  453.       seek_dp -> dp_Arg1 = fh -> fh_Arg1;
  454.       seek_dp -> dp_Arg2 = seek_pos;
  455.       seek_dp -> dp_Arg3 = seek_mode;
  456.  
  457.       seek_dp -> dp_Port = seek_dp -> dp_Link -> mn_ReplyPort = mp;
  458.       PutMsg( (fh -> fh_Type), (seek_dp -> dp_Link) );
  459.       numpkt++;
  460.     }
  461.  
  462.     /* Send read */
  463.     read_sp . sp_Msg . mn_Node . ln_Type = NT_MESSAGE;
  464.     read_sp . sp_Msg . mn_Node . ln_Name = (STRPTR)read_dp;
  465.     read_sp . sp_Msg . mn_Length         = sizeof( struct DosPacket );
  466.     read_sp . sp_Pkt . dp_Link           = (&(read_sp . sp_Msg));
  467.  
  468.     read_dp -> dp_Type = ACTION_READ;
  469.     read_dp -> dp_Arg1 = fh -> fh_Arg1;
  470.     read_dp -> dp_Arg2 = (LONG)read_buffer;
  471.     read_dp -> dp_Arg3 = read_len;
  472.  
  473.     read_dp -> dp_Port = read_dp -> dp_Link -> mn_ReplyPort = mp;
  474.     PutMsg( (fh -> fh_Type), (read_dp -> dp_Link) );
  475.     numpkt++;
  476.  
  477.     /* Wait for outstanding msgs and fetch success/errorc codes from them */
  478.     while( numpkt > 0L )
  479.     {
  480.       struct Message *msg;
  481.  
  482.       WaitPort( mp );
  483.  
  484.       while( msg = GetMsg( mp ) )
  485.       {
  486.         struct DosPacket *rdp = (struct DosPacket *)(msg -> mn_Node . ln_Name);
  487.  
  488.         /* This assumes that we only get ACTION_SEEK/ACTION_READ here back... */
  489.         if( (rdp -> dp_Res1) == -1L )
  490.         {
  491.           error = rdp -> dp_Res2; /* BUG: It is not expected that a handler returns 0 here... */
  492.         }
  493.  
  494.         numpkt--;
  495.       }
  496.     }
  497.  
  498.     if( !error )
  499.     {
  500.       reslen = read_dp -> dp_Res1;
  501.     }
  502.     else
  503.     {
  504.       SetIoErr( error );
  505.     }
  506.  
  507.     return( reslen );
  508. }
  509.  
  510.  
  511.